﻿using Newtonsoft.Json.Converters;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace AVCUMPlatform.HelperLibrary
{
    public static class Util
    {
        /// <summary>
        /// 默认密码
        /// </summary>
        public static readonly string DefaultPassword = MD5Encrypt("pw_a1b2c3");

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="toCryString"></param>
        /// <returns></returns>
        public static string MD5Encrypt(string toCryString)
        {
            var hashmd5 = MD5.Create();
            return BitConverter.ToString(hashmd5.ComputeHash(Encoding.Default.GetBytes(toCryString))).Replace("-", "").ToUpper();
        }

        /// <summary>
        /// 16位的MD5加密
        /// </summary>
        /// <param name="password"></param>
        /// <returns></returns>
        public static string MD5Encrypt16(string password)
        {
            var md5 = MD5.Create();
            string t2 = BitConverter.ToString(md5.ComputeHash(Encoding.Default.GetBytes(password)), 4, 8);
            t2 = t2.Replace("-", "");
            return t2;
        }

        /// <summary>
        /// 32位MD5加密
        /// </summary>
        /// <param name="password"></param>
        /// <returns></returns>
        public static string MD5Encrypt32(string password)
        {
            string cl = password;
            string pwd = "";
            MD5 md5 = MD5.Create(); //实例化一个md5对像
                                    // 加密后是一个字节类型的数组，这里要注意编码UTF8/Unicode等的选择　
            byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));
            // 通过使用循环，将字节类型的数组转换为字符串，此字符串是常规字符格式化所得
            for (int i = 0; i < s.Length; i++)
            {
                // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母，如果使用大写（X）则格式后的字符是大写字符 
                pwd = pwd + s[i].ToString("X2");
            }
            return pwd;
        }


        /// <summary>
        /// MD532位小写
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string MD532(string str)
        {
            var md5Hasher = MD5.Create();
            byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(str));
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));//转化为小写的16进制
            }
            return sBuilder.ToString();
        }
        /// <summary>
        /// 64位的MD5加密
        /// </summary>
        /// <param name="password"></param>
        /// <returns></returns>
        public static string MD5Encrypt64(string password)
        {
            string cl = password;
            //string pwd = "";
            MD5 md5 = MD5.Create(); //实例化一个md5对像
                                    // 加密后是一个字节类型的数组，这里要注意编码UTF8/Unicode等的选择　
            byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));
            return Convert.ToBase64String(s);
        }

        /// <summary>
        /// 生成GUID
        /// </summary>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public static string CreateGUID(int type = 1)
        {
            var uuid = "";
            switch (type)
            {
                case 0:
                    uuid = Guid.NewGuid().ToString(); // 9af7f46a-ea52-4aa3-b8c3-9fd484c2af12
                    break;
                case 1:
                    uuid = Guid.NewGuid().ToString("N"); // e0a953c3ee6040eaa9fae2b667060e09
                    break;
                case 2:
                    uuid = Guid.NewGuid().ToString("D"); // 9af7f46a-ea52-4aa3-b8c3-9fd484c2af12
                    break;
                case 3:
                    uuid = Guid.NewGuid().ToString("B"); // {734fd453-a4f8-4c5d-9c98-3fe2d7079760}
                    break;
                case 4:
                    uuid = Guid.NewGuid().ToString("P"); // (ade24d16-db0f-40af-8794-1e08e2040df3)
                    break;
                case 5:
                    uuid = Guid.NewGuid().ToString("X"); // {0x3fa412e3,0x8356,0x428f,{0xaa,0x34,0xb7,0x40,0xda,0xaf,0x45,0x6f}}
                    break;
            }
            return uuid;
        }

        /// <summary>
        /// 获取枚举类型的描述
        /// </summary>
        /// <param name="enumeration"></param>
        /// <returns></returns>
        public static string ToDescription(this Enum enumeration)
        {
            Type type = enumeration.GetType();
            MemberInfo[] memInfo = type.GetMember(enumeration.ToString());
            if (null != memInfo && memInfo.Length > 0)
            {
                object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (null != attrs && attrs.Length > 0)
                    return ((DescriptionAttribute)attrs[0]).Description;
            }
            return enumeration.ToString();
        }
        /// <summary>
        /// 获取枚举类型的描述
        /// </summary>
        /// <param name="enumeration"></param>
        /// <returns></returns>
        public static string ToDescription2(this Enum enumeration)
        {
            Type type = enumeration.GetType();
            MemberInfo[] memInfo = type.GetMember(enumeration.ToString());
            if (null != memInfo && memInfo.Length > 0)
            {
                object[] attrs = memInfo[0].GetCustomAttributes(typeof(Description2Attribute), false);
                if (null != attrs && attrs.Length > 0)
                    return ((Description2Attribute)attrs[0]).Description;
            }
            return enumeration.ToString();
        }
        /// <summary>  
        /// 判断两个日期是否在同一周  
        /// </summary>  
        /// <param name="dtmS">开始日期</param>  
        /// <param name="dtmE">结束日期</param> 
        /// <returns></returns>  
        public static bool IsInSameWeek(DateTime dtmS, DateTime dtmE)
        {
            TimeSpan ts = dtmE - dtmS;
            double dbl = ts.TotalDays;
            int intDow = Convert.ToInt32(dtmE.DayOfWeek);
            if (intDow == 0) intDow = 7;
            if (dbl >= 7 || dbl >= intDow) return false;
            else return true;
        }

        /// <summary>
        /// 对象转Json字符串
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ObjectToJson(object obj)
        {
            JsonSerializerSettings jss = new JsonSerializerSettings();

            IsoDateTimeConverter timeConverter = new IsoDateTimeConverter();
            timeConverter.DateTimeFormat = "yyyy'-'MM'-'dd' 'HH':'mm':'ss";//日期转化为字符串类型

            //jss.ContractResolver = new LowercaseContractResolver();//Column转化为小写
            jss.Converters.Add(timeConverter);

            return JsonConvert.SerializeObject(obj, Newtonsoft.Json.Formatting.Indented, jss);
        }

        /// <summary>
        /// Json字符串转对象
        /// </summary>
        /// <param name="jsonString"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static object JsonToObject(string jsonString, object obj)
        {
            return JsonConvert.DeserializeObject(jsonString, obj.GetType());
        }

        /// <summary>
        /// 过滤查询参数中的特殊字符
        /// </summary>
        public static object QueryParameterFilter(object model)
        {
            if (model == null)
            {
                return model;
            }
            Type type = model.GetType();
            if (type.Name.ToLower() == "string")
            {
                model = model.ToString().Replace("%", "\\%").Replace("'", @"\'").Replace("_", @"\_");
            }
            else
            {
                var list = type.GetProperties();
                foreach (var item in list)
                {
                    if (item.PropertyType.Name.ToLower() == "string")
                    {
                        var value = item.GetValue(model);
                        if (value != null)
                        {
                            value = value.ToString().Replace("%", "\\%").Replace("'", @"\'").Replace("_", @"\_");
                            item.SetValue(model, value);
                        }
                    }
                }
            }
            return model;
        }

        /// <summary>
        /// 16进制原码字符串转字节数组
        /// </summary>
        /// <param name="hexString">"AABBCC"或"AA BB CC"格式的字符串</param>
        /// <returns></returns>
        public static byte[] ConvertHexStringToBytes(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if (hexString.Length % 2 != 0)
            {
                throw new ArgumentException("参数长度不正确");
            }

            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
            {
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            }

            return returnBytes;
        }

        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string ByteArrayToHexString(byte[] data)
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (byte b in data)
            {
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0'));
            }
            return sb.ToString().ToUpper();
        }

        /// <summary>
        /// 16进制字符串转字节数组
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        public static byte[] HexStringToByteArray(string hexString)
        {
            byte[] byteArray = new byte[hexString.Length / 2];
            for (int x = 0; x < byteArray.Length; x++)
            {
                var i = Convert.ToInt32(hexString.Substring(x * 2, 2), 16);
                byteArray[x] = (byte)i;
            }
            return byteArray;
        }

        /// <summary>
        /// 列表空判断
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public static bool ListIsNullOrEmpty<T>(List<T> list)
        {
            if (list == null || list.Count == 0)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 加密盐
        /// </summary>
        public static readonly string EncryptSalt = "_avc_";


        /// <summary>
        /// 电话号码隐藏
        /// </summary>
        /// <param name="telephoneSource"></param>
        /// <returns></returns>
        public static string PhoneHide(string telephoneSource)
        {
            string telephone = string.Empty;
            if (!string.IsNullOrEmpty(telephoneSource)
                && telephoneSource.Contains(EncryptSalt))
            {
                string partStart = telephoneSource.Substring(0, 3);
                string partEnd = telephoneSource.Substring(telephoneSource.Length - 4, 4);
                telephone = $"{partStart}****{partEnd}";
            }
            return telephone;
        }

        /// <summary>
        /// 获取校园卡类型名称
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetCardTypeName(int type)
        {
            switch (type)
            {
                case 1:
                    return "管理卡";
                case 2:
                    return "普通卡";
                case 3:
                    return "学生卡";
                default:
                    return "未知类型";
            }
        }

        /// <summary>
        /// 获取校园卡刷卡状态名称
        /// </summary>
        /// <param name="status"></param>
        /// <returns></returns>
        public static string GetCardLogStatusName(int status)
        {
            switch (status)
            {
                case 0:
                    return "刷卡/插卡失败";
                case 1:
                    return "刷卡/插卡成功";
                case 2:
                    return "拔卡成功";
                default:
                    return "未知类型";
            }
        }

        /// <summary>
        /// 获取性别名称
        /// </summary>
        /// <param name="gender"></param>
        /// <returns></returns>
        public static string GetGenderName(int gender)
        {
            switch (gender)
            {
                case 0:
                    return "未知";
                case 1:
                    return "男";
                case 2:
                    return "女";
                default:
                    return "未知类型";
            }
        }

        /// <summary>
        /// 获取用户类型名称
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetUserTypeName(int type)
        {
            switch (type)
            {
                case 1:
                    return "教师";
                case 2:
                    return "学生";
                default:
                    return "其它";
            }
        }
        ///编码
        public static string EncodeBase64(string code_type, string code)
        {
            string encode = "";
            byte[] bytes = Encoding.GetEncoding(code_type).GetBytes(code);
            try
            {
                encode = Convert.ToBase64String(bytes);
            }
            catch
            {
                encode = code;
            }
            return encode;
        }
        ///解码
        public static string DecodeBase64(string code_type, string code)
        {
            string decode = "";
            byte[] bytes = Convert.FromBase64String(code);
            try
            {
                decode = Encoding.GetEncoding(code_type).GetString(bytes);
            }
            catch
            {
                decode = code;
            }
            return decode;
        }
        /// <summary>
        /// 字符串还原
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string Base64DecryptFiler(string str)
        {
            str = str.Replace("~", "=");
            str = str.Replace("_", "/");
            str = str.Replace("-", "+");
            return str;
        }

        /// <summary>
        /// HmacSHA256加密
        /// </summary>
        /// <param name="secret"></param>
        /// <param name="signKey"></param>
        /// <returns></returns>
        public static string HmacSHA256(string secret, string signKey)
        {
            string signRet = string.Empty;
            using (HMACSHA256 mac = new HMACSHA256(Encoding.UTF8.GetBytes(signKey)))
            {
                byte[] hash = mac.ComputeHash(Encoding.UTF8.GetBytes(secret));
                signRet = Convert.ToBase64String(hash);
                //signRet = ToHexString(hash); ;
            }
            return signRet;
        }

        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        /// <summary>
        /// URL编码
        /// </summary>
        /// <param name="temp"></param>
        /// <returns></returns>
        public static string UrlEncodeStr(string temp)
        {
            StringBuilder builder = new StringBuilder();
            foreach (char c in temp)
            {
                if (HttpUtility.UrlEncode(c.ToString()).Length > 1)
                {
                    builder.Append(HttpUtility.UrlEncode(c.ToString()).ToUpper());
                }
                else
                {
                    builder.Append(c);
                }
            }
            //Encoding encoding = Encoding.UTF8;
            //string str = HttpUtility.UrlEncode(temp, encoding);
            return builder.ToString();
        }
        /// <summary>
        /// 批量处理任务工具方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tList"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="action"></param>
        public static void BatchProcess<T>(List<T> tList, int pageSize, Action<List<T>> action)
        {
            if (tList == null || !tList.Any())
            {
                return;
            }

            int pageIndex = 1;
            List<T> tempList = tList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            while (tempList.Any())
            {
                action.Invoke(tempList);
                pageIndex += 1;
                tempList = tList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            }
        }
        /// <summary>
        /// 获取百分比
        /// </summary>
        /// <param name="part"></param>
        /// <param name="total"></param>
        /// <returns></returns>
        public static string GetPercent(double part, double total)
        {
            if (part == 0 || total == 0)
            {
                return $"0%";
            }
            double res = (part / total) * 100;
            if (res < 0.01)
            {
                res = 0.01;
            }
            return $"{res.ToString("0.##")}%";
        }

        /// <summary>
        /// 获取百分比
        /// </summary>
        /// <param name="part"></param>
        /// <param name="total"></param>
        /// <returns></returns>
        public static double GetPercentNum(double part, double total)
        {
            if (part == 0 || total == 0)
            {
                return 0;
            }
            double res = (part / total) * 100;
            if (res < 0.01)
            {
                res = 0.01;
            }
            return Convert.ToDouble(res.ToString("0.##"));
        }


        /// <summary>
        /// 获取两位数相除
        /// </summary>
        /// <param name="part"></param>
        /// <param name="total"></param>
        /// <returns></returns>
        public static double GetNum(double part, double total)
        {
            if (part == 0 || total == 0)
            {
                return 0;
            }
            double res = (part / total * 1.0);
            if (res < 0.01)
            {
                res = 0.01;
            }
            double num = Math.Round(res, 2, MidpointRounding.AwayFromZero);
            return num;
        }

        /// <summary>
        /// 小数点处理两位
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public static double DoubleProcess(double num)
        {
            double res = Math.Round(num, 2, MidpointRounding.AwayFromZero);
            if (num > 0 && res == 0)
            {
                res = 0.01;
            }
            return res;
        }
        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="fileDirect"></param>
        /// <param name="saveDay"></param>
        public static void DeleteFile(List<string> fileDirects, int saveDay)
        {
            DateTime nowTime = DateTime.Now;
            foreach (string fileDirect in fileDirects)
            {
                if (!Directory.Exists(fileDirect))
                {
                    continue;
                }
                string[] files = Directory.GetFiles(fileDirect, "*.log", SearchOption.AllDirectories);  //获取该目录下所有 .txt文件
                foreach (string file in files)
                {
                    FileInfo fileInfo = new FileInfo(file);
                    TimeSpan t = nowTime - fileInfo.CreationTime;  //当前时间  减去 文件创建时间
                    int day = t.Days;
                    if (day > saveDay)   //保存的时间 ；  单位：天
                    {
                        File.Delete(file);  //删除超过时间的文件
                    }
                }
            }
        }

        /// <summary>
        /// 获取地址
        /// </summary>
        /// <param name="addr"></param>
        /// <param name="nginxStr"></param>
        /// <returns></returns>
        public static string GetAddress(string addr, string nginxStr)
        {
            if (string.IsNullOrWhiteSpace(nginxStr))
            {
                return addr;
            }
            string address = string.Empty;
            if (!string.IsNullOrWhiteSpace(addr))
            {
                string[] strs = addr.Split("://");
                string head = addr.Substring(0, addr.IndexOf(":"));
                address = $"{strs[0]}://{nginxStr}/{head}_proxy/{strs[1]}";
            }
            return address;
        }

        /// <summary>
        /// id 列表转换为字符串，方括号附近添加 逗号，便于模糊查询
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public static string ToDBStr(List<int> ids)
        {
            if (ListIsNullOrEmpty(ids))
            {
                return "[]";
            }
            string str = JsonConvert.SerializeObject(ids);
            str = str.Replace("[", "[,").Replace("]", ",]");
            return str;
        }

        /// <summary>
        /// 数据库存的 Id 字符串 转换为列表
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static List<int> ToIdList(string str)
        {
            if (string.IsNullOrEmpty(str) || str == "[]")
            {
                return new List<int>();
            }
            str = str.Replace("[,", "[").Replace(",]", "]");
            return JsonConvert.DeserializeObject<List<int>>(str);
        }

        /// <summary>
        /// ip还原
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static string DecomposeIp(string ip)
        {
            string str1 = ip.Substring(0, 3);
            string str2 = ip.Substring(3, 3);
            string str3 = ip.Substring(6, 3);
            string str4 = ip.Substring(9, 3);
            return $"{Convert.ToInt32(str1)}.{Convert.ToInt32(str2)}.{Convert.ToInt32(str3)}.{Convert.ToInt32(str4)}";
        }
        /// <summary>
        /// 获取拼接字符cover
        /// </summary>
        /// <param name="cover"></param>
        /// <returns></returns>
        public static string GetPathAddr(string path)
        {
            string str = string.Empty;
            if (!string.IsNullOrWhiteSpace(path))
            {
                string[] strArray = path.Split("://");
                int t = strArray[1].IndexOf("/");
                string heardStr = $"{strArray[0]}://{strArray[1].Substring(0, t)}";
                str = strArray[1].Substring(t);
            }
            return str;
        }

        /// <summary>
        /// 指定长度截取字符串
        /// </summary>
        /// <param name="cover"></param>
        /// <returns></returns>
        public static string Substring(string str, int len)
        {
            if (string.IsNullOrEmpty(str))
            {
                return " ";
            }
            if (len > str.Length)
            {
                return str;
            }
            return str.Substring(0, len) + "...";
        }

        public static string RobotSignAndTimestamp(string secret_key)
        {
            long timestamp = GetRobotTimeStamp();
            string sign = Util.HmacSHA256(secret_key, timestamp);
            return $"sign={sign}&timestamp={timestamp}";
        }

        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public static long GetRobotTimeStamp()
        {
            long timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
            return timestamp;
        }


        /// <summary>
        /// HmacSHA256加密
        /// </summary>
        /// <param name="secret"></param>
        /// <param name="signKey"></param>
        /// <returns></returns>
        public static string HmacSHA256(string secret, long timestamp)
        {
            string encodeSign = string.Empty;
            string stringToSign = timestamp + "\n" + secret;
            using (HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret)))
            {
                byte[] hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
                string sign = Convert.ToBase64String(hash);
                encodeSign = HttpUtility.UrlEncode(sign);
            }
            return encodeSign;
        }
    }
}
